package se19team1e.gui.awt;

import java.awt.Checkbox;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Date;
import java.util.List;

import javax.swing.JPanel;

import se19team1e.entity.CompanyDTO;
import se19team1e.entity.DepartmentDTO;
import se19team1e.entity.JobAdvertDTO;
import se19team1e.gui.MessageBoxHelper;
import se19team1e.util.FloatUtil;
import se19team1e.util.StringUtil;

/**
 * 
 * A GUI panel for showing the job advert input fields.
 * 
 * <p>
 * Contains all the input fields related to a job advert create/update.
 * </p>
 * 
 * @author lai shiaw san
 *
 */
public class JobAdvertInputPanel extends JPanel {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    /**
     * An awt text field to enter title.
     */
    public final TextField titleField;

    /**
     * An awt text field to enter description.
     */
    public final TextField descriptionField;

    /**
     * An awt combo box to select company.
     */
    public final CompanyComboBox companyComboBox;
    
    /**
     * Label to describe 'use company description' checkbox
     */
    public final Label useCompanyDescriptionLabel;
    
    /**
     * An awt checkbox to use company description.
     */
    public final Checkbox useCompanyDescriptionCheckbox;

    /**
     * An awt combo box to select department.
     */
    public final DepartmentComboBox departmentComboBox;

    /**
     * An awt text field to enter experience.
     */
    public final TextField experienceField;

    /**
     * An awt text field to enter location.
     */
    public final TextField locationField;

    /**
     * An awt text field to enter skills.
     */
    public final TextField skillsField;

    /**
     * An awt text field to enter salary.
     */
    public final TextField salaryField;

    /**
     * An awt text field to enter start date.
     */
    public final DateField startDateField;

    /**
     * An awt label for displaying company description.
     */
    public final Label companyDescription;

    private JobAdvertDTO jobAdvertDTO=null;
    /**
     * Constructs the login input panel.
     */
    public JobAdvertInputPanel() {

        final int TITLE_INPUTWIDTH = 20;
        final int DESCRIPTION_INPUTWIDTH = 20;
        final int EXPERIENCE_INPUTWIDTH = 20;
        final int LOCATION_INPUTWIDTH = 20;
        final int SKILLS_INPUTWIDTH = 20;
        final int SALARY_INPUTWIDTH = 20;
        final int STARTDATE_MINYEAR = 2010;
        final int STARTDATE_MAXYEAR = 2012;

        this.setLayout( new GridLayout( 0, 2 ) );
        
        // create and add the title field
        this.titleField = new TextField( TITLE_INPUTWIDTH );
        this.add( new Label( "Title" ) );
        this.add( this.titleField );

        // create and add the description field
        this.descriptionField = new TextField( DESCRIPTION_INPUTWIDTH );
        this.add( new Label( "Description" ) );
        this.add( this.descriptionField );

        // create and add the company field
        this.companyComboBox = new CompanyComboBox();
        this.add( new Label( "Company" ) );
        this.add( this.companyComboBox );

        // create and add the use company description field)
        this.useCompanyDescriptionLabel = new Label( "Use Company Description" );
        this.useCompanyDescriptionCheckbox = new Checkbox();
        this.add(this.useCompanyDescriptionLabel);
        this.add( this.useCompanyDescriptionCheckbox );
        
        // create company description field but don't add it into the panel first.
        this.companyDescription = new Label();

        // create and add the department field
        boolean allowNull = true;
        this.departmentComboBox = new DepartmentComboBox( allowNull );
        this.add( new Label( "Department" ) );
        this.add( this.departmentComboBox );
        
        // update department list when company changes
        this.companyComboBox.addItemListener( new ItemListener() {
            @Override
            public void itemStateChanged( ItemEvent e ) {
                departmentComboBox.refreshListBaseOnCompanyId( getCompanyIdInput() );
            }
        });

        // create and add the experience field
        this.experienceField = new TextField( EXPERIENCE_INPUTWIDTH );
        this.add( new Label( "Experience" ) );
        this.add( this.experienceField );

        // create and add the location field
        this.locationField = new TextField( LOCATION_INPUTWIDTH );
        this.add( new Label( "Location" ) );
        this.add( this.locationField );

        // create and add the salary field
        this.salaryField = new TextField( SALARY_INPUTWIDTH );
        this.add( new Label( "Salary" ) );
        this.add( this.salaryField );

        // create and add the skills field
        this.skillsField = new TextField( SKILLS_INPUTWIDTH );
        this.add( new Label( "Skills" ) );
        this.add( this.skillsField );

        // create and add the start date field
        this.startDateField = new DateField( STARTDATE_MINYEAR, STARTDATE_MAXYEAR );
        this.add( new Label( "Start Date" ) );
        this.add( this.startDateField );

    }
    
    /**
     * Clears any previous input, and reset the combo boxes.
     * 
     * @param companies Companies to display in the form.
     * @param departments Departments to display in the form.
     */
    public void initialize(JobAdvertDTO jobAdvertDTO, List<CompanyDTO> companies, List<DepartmentDTO> departments ) { 
        // reset company combo box
    	this.jobAdvertDTO=jobAdvertDTO;
        this.companyComboBox.initialize( companies );
        
        // reset department combo box
        this.departmentComboBox.initialize( departments );
        this.departmentComboBox.refreshListBaseOnCompanyId( getCompanyIdInput() );

        if (jobAdvertDTO.getCompanyId()!=null){
        	companyComboBox.select(jobAdvertDTO.getCompanyName());
        	this.departmentComboBox.refreshListBaseOnCompanyId(jobAdvertDTO.getCompanyId());
        }
        if (jobAdvertDTO.getDepartmentId()!=null){
        	departmentComboBox.select(jobAdvertDTO.getDepartmentName());
        }
        // clears any previous input 
        this.titleField.setText( jobAdvertDTO.getTitle() );
        this.descriptionField.setText(jobAdvertDTO.getDescription() );
        this.experienceField.setText(jobAdvertDTO.getExperience() );
        this.locationField.setText(jobAdvertDTO.getLocation());
        this.skillsField.setText(jobAdvertDTO.getSkills());
        this.salaryField.setText(String.valueOf(jobAdvertDTO.getSalary()));
        this.startDateField.resetValues(jobAdvertDTO.getStartDate());
        this.useCompanyDescriptionCheckbox.setState( jobAdvertDTO.isUseCompanyDescription() );
    }

    /**
     * Validates the job advert input to see if it is valid.
     * 
     * <p>
     * Returns false if validation fails.
     * </p>
     * <p>
     * Displays an error message if it fails, using a message box.
     * </p>
     * @param messageBoxHelper Helper to create message boxes.
     * @return True if valid.
     */
    public boolean validateInput( MessageBoxHelper messageBoxHelper ) {
        // check for empty entry
        if ( StringUtil.isEmptyOrNull( this.getTitleInput() ) ) {
            // failure, display error message
            messageBoxHelper.displayMissingInputErrorMessage( "title" );
            
            return false; 
        }
        if ( StringUtil.isEmptyOrNull( this.getDescriptionInput() ) ) {
            // failure, display error message
            messageBoxHelper.displayMissingInputErrorMessage( "description" );
            
            return false; 
        }
        if ( StringUtil.isEmptyOrNull( this.getCompanyIdInput() ) ) {
            // failure, display error message
            messageBoxHelper.displayMissingInputErrorMessage( "company" );
            
            return false; 
        }
        
        // allow no department to be selected
        
        if ( StringUtil.isEmptyOrNull( this.getExperienceInput() ) ) {
            // failure, display error message
            messageBoxHelper.displayMissingInputErrorMessage( "experience" );
            
            return false; 
        }
        if ( StringUtil.isEmptyOrNull( this.getLocationInput() ) ) {
            // failure, display error message
            messageBoxHelper.displayMissingInputErrorMessage( "location" );
            
            return false; 
        }
        if ( StringUtil.isEmptyOrNull( this.getSalaryInput() ) ) {
            // failure, display error message
            messageBoxHelper.displayMissingInputErrorMessage( "salary" );
            
            return false; 
        }
        if ( !FloatUtil.isFloat( this.getSalaryInput() ) ) {
            // failure, display error message
            messageBoxHelper.displayMessage( "Error", "Enter a numeric value for salary", new ActionListener() {
                @Override
                public void actionPerformed( ActionEvent e ) {
                    // do nothing
                }
            });
            
            return false; 
        }
        if ( StringUtil.isEmptyOrNull( this.getSkillsInput() ) ) {
            // failure, display error message
            messageBoxHelper.displayMissingInputErrorMessage( "skills" );
            
            return false; 
        }

        return true;
    }

    /**
     * Get the company id in the selection box.
     * @return Value in input box.
     */
    public String getCompanyIdInput() {
        return this.companyComboBox.getSelectedCompanyId();
    }
    
    /**
     * Gets the use company description check box selection value.
     * @return Value in check box.
     */
    public boolean getUseCompanyDescriptionInput() {
        return this.useCompanyDescriptionCheckbox.getState();
    }

    /**
     * Get the department id in the selection box.
     * @return Value in input box.
     */
    public String getDepartmentIdInput() {
        return this.departmentComboBox.getSelectedDepartmentId( this.getCompanyIdInput() );
    }

    /**
     * Get the description in the input box.
     * @return Value in input box.
     */
    public String getDescriptionInput() {
        return this.descriptionField.getText();
    }

    /**
     * Get the experience in the input box.
     * @return Value in input box.
     */
    public String getExperienceInput() {
        return this.experienceField.getText();
    }

    /**
     * Get the location in the input box.
     * @return Value in input box.
     */
    public String getLocationInput() {
        return this.locationField.getText();
    }

    /**
     * Get the salary in the input box.
     * @return Value in input box.
     */
    public String getSalaryInput() {
        return this.salaryField.getText();
    }
    
    /**
     * Get the skills in the input box.
     * @return Value in input box.
     */
    public String getSkillsInput() {
        return this.skillsField.getText();
    }

    /**
     * Get the start date as date
     * @return Value in input box converted to date.
     */
    public Date getStartDateInputAsDate() {
        return this.startDateField.getValueAsDate();
    }

    /**
     * Get the title in the input box.
     * @return Value in input box.
     */
    public String getTitleInput() {
        return this.titleField.getText();
    }

    /**
     * Create a new JobAdvertDTO object from the input.
     * @return New JobAdvertDTO from the input.
     */
    public JobAdvertDTO newJobAdvertDTOFromInput() {
        JobAdvertDTO jobAdvert = new JobAdvertDTO();

        jobAdvert.setTitle( this.getTitleInput() );
        jobAdvert.setDescription( this.getDescriptionInput() );
        jobAdvert.setCompanyId( this.getCompanyIdInput() );
        jobAdvert.setUseCompanyDescription( this.getUseCompanyDescriptionInput() );
        jobAdvert.setDepartmentId( this.getDepartmentIdInput() );
        jobAdvert.setExperience( this.getExperienceInput() );
        jobAdvert.setLocation( this.getLocationInput() );
        jobAdvert.setSalary( FloatUtil.toFloat( this.getSalaryInput() ) );
        jobAdvert.setSkills( this.getSkillsInput() );
        jobAdvert.setStartDate( this.getStartDateInputAsDate() );
        
        return jobAdvert;
    }
    
    /**
     * Create a new JobAdvertDTO object from the input.
     * @return New JobAdvertDTO from the input.
     */
    public JobAdvertDTO newJobAdvertDTOFromInputForUpdate(JobAdvertDTO jobAdvert) {
        jobAdvert.setId(this.jobAdvertDTO.getId());

        jobAdvert.setTitle( this.getTitleInput() );
        jobAdvert.setDescription( this.getDescriptionInput() );
        jobAdvert.setCompanyId( this.getCompanyIdInput() );
        jobAdvert.setUseCompanyDescription( this.getUseCompanyDescriptionInput() );
        jobAdvert.setDepartmentId( this.getDepartmentIdInput() );
        jobAdvert.setExperience( this.getExperienceInput() );
        jobAdvert.setLocation( this.getLocationInput() );
        jobAdvert.setSalary( FloatUtil.toFloat( this.getSalaryInput() ) );
        jobAdvert.setSkills( this.getSkillsInput() );
        jobAdvert.setStartDate( this.getStartDateInputAsDate() );
        
        return jobAdvert;
    }

    
    /**
     * Sets all inputs to read-only and disabled them.
     * 
     */
    public void setReadOnly() { 
        // reset company combo box
        this.companyComboBox.setEnabled(false);
        this.departmentComboBox.setEnabled(false);
        this.titleField.setEnabled(false);
        this.titleField.setEditable(false);
        this.descriptionField.setEnabled(false);
        this.descriptionField.setEditable(false);
        this.experienceField.setEnabled(false);
        this.experienceField.setEditable(false);
        this.locationField.setEnabled(false);
        this.locationField.setEditable(false);
        this.skillsField.setEnabled(false);
        this.skillsField.setEditable(false);
        this.salaryField.setEnabled(false);
        this.salaryField.setEditable(false);
        this.useCompanyDescriptionCheckbox.setEnabled(false);
        this.startDateField.setEnabled(false);
        this.startDateField.enableDateFieldSelection(false);
        //this.startDateField.resetValues(jobAdvertDTO.getStartDate());
    }
    
    /**
     * Removes Company Description Label and Checkbox 
     * (will be called if logged in as a non-advertiser)
     */
    public void removesCompanyDescription() {
    	this.remove(this.useCompanyDescriptionLabel);
    	this.remove(this.useCompanyDescriptionCheckbox);
    }
    
    public void addCompanyDescription(String companyDescription) {
    	this.remove(this.companyComboBox);
    	this.companyDescription.setText(companyDescription);
    	this.add(this.companyDescription, 5);
    }
}
